{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ccd55819",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 安装所需软件包\n",
    "\n",
    "!pip install -U langgraph langsmith"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6cdfef86",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(AIMessageChunk(content='Hello', additional_kwargs={}, response_metadata={}, id='run--be118411-b343-4faf-a8b5-805899090951'), {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ('branch:to:agent',), 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'ls_provider': 'tongyi', 'ls_model_type': 'chat', 'ls_model_name': 'qwen-turbo'})\n",
      "\n",
      "\n",
      "(AIMessageChunk(content='!', additional_kwargs={}, response_metadata={}, id='run--be118411-b343-4faf-a8b5-805899090951'), {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ('branch:to:agent',), 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'ls_provider': 'tongyi', 'ls_model_type': 'chat', 'ls_model_name': 'qwen-turbo'})\n",
      "\n",
      "\n",
      "(AIMessageChunk(content=' How', additional_kwargs={}, response_metadata={}, id='run--be118411-b343-4faf-a8b5-805899090951'), {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ('branch:to:agent',), 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'ls_provider': 'tongyi', 'ls_model_type': 'chat', 'ls_model_name': 'qwen-turbo'})\n",
      "\n",
      "\n",
      "(AIMessageChunk(content=' can', additional_kwargs={}, response_metadata={}, id='run--be118411-b343-4faf-a8b5-805899090951'), {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ('branch:to:agent',), 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'ls_provider': 'tongyi', 'ls_model_type': 'chat', 'ls_model_name': 'qwen-turbo'})\n",
      "\n",
      "\n",
      "(AIMessageChunk(content=' I assist you today', additional_kwargs={}, response_metadata={}, id='run--be118411-b343-4faf-a8b5-805899090951'), {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ('branch:to:agent',), 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'ls_provider': 'tongyi', 'ls_model_type': 'chat', 'ls_model_name': 'qwen-turbo'})\n",
      "\n",
      "\n",
      "(AIMessageChunk(content='? 😊', additional_kwargs={}, response_metadata={}, id='run--be118411-b343-4faf-a8b5-805899090951'), {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ('branch:to:agent',), 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'ls_provider': 'tongyi', 'ls_model_type': 'chat', 'ls_model_name': 'qwen-turbo'})\n",
      "\n",
      "\n",
      "(AIMessageChunk(content='', additional_kwargs={}, response_metadata={'finish_reason': 'stop', 'request_id': '6e0e6cee-47a1-4476-b6fe-8baea463fca0', 'token_usage': {'input_tokens': 23, 'output_tokens': 11, 'total_tokens': 34, 'prompt_tokens_details': {'cached_tokens': 0}}}, id='run--be118411-b343-4faf-a8b5-805899090951'), {'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ('branch:to:agent',), 'langgraph_path': ('__pregel_pull', 'agent'), 'langgraph_checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'checkpoint_ns': 'agent:958f81bf-a3ee-2bb6-f936-d7ac1297c519', 'ls_provider': 'tongyi', 'ls_model_type': 'chat', 'ls_model_name': 'qwen-turbo'})\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# langgraph Hello World\n",
    "from langgraph.prebuilt import create_react_agent\n",
    "from langchain_community.chat_models import ChatTongyi\n",
    "\n",
    "llm = ChatTongyi(\n",
    "    model_name=\"qwen-turbo\",\n",
    "    temperature=0.7,\n",
    "    streaming=True\n",
    ")\n",
    "\n",
    "agent = create_react_agent(\n",
    "    model = llm,\n",
    "    tools = [],\n",
    "    prompt= \"You are a helpful assistant.\"\n",
    ")\n",
    "\n",
    "# agent.invoke({\"message\":[{\"role\":\"user\",\"content\":\"Hello, how can I help you?\"}]})\n",
    "for chunk in agent.stream(\n",
    "    {\"message\":[{\"role\":\"user\",\"content\":\"你是谁？\"}]},\n",
    "    stream_mode = \"messages\"\n",
    "):\n",
    "    print(chunk)\n",
    "    print(\"\\n\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05203d66",
   "metadata": {},
   "source": [
    "创建一个 StateGraph 为“状态机”,添加 节点 来表示 LLM 和聊天机器人可以调用的函数，并添加 边 来指定机器人应如何在这些函数之间进行转换。\n",
    "\n",
    "> 定义：定义图时，第一步是定义其 状态。状态 包括图的模式和处理状态更新的 reducer 函数。在我们的示例中，状态 是一个具有一个键：messages 的 TypedDict。 add_messages reducer 函数用于将新消息追加到列表中，而不是覆盖它。没有 reducer 注解的键将覆盖先前的值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d24b482",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Annotated\n",
    "\n",
    "from typing_extensions import TypedDict\n",
    "\n",
    "from langgraph.graph import StateGraph, START\n",
    "from langgraph.graph.message import add_messages\n",
    "\n",
    "class State(TypedDict):\n",
    "    # Messages have the type \"list\". The `add_messages` function\n",
    "    # in the annotation defines how this state key should be updated\n",
    "    # (in this case, it appends messages to the list, rather than overwriting them)\n",
    "    messages: Annotated[list, add_messages]\n",
    "\n",
    "\n",
    "graph_builder = StateGraph(State)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef485601",
   "metadata": {},
   "source": [
    "我们的图现在可以处理两个关键任务\n",
    "\n",
    "每个 节点 都可以接收当前 状态 作为输入，并输出状态的更新。\n",
    "对 消息 的更新将追加到现有列表而不是覆盖它。\n",
    "\n",
    "\n",
    "接下来，添加一个“chatbot”节点。 节点 表示工作单元，通常是普通的 Python 函数。\n",
    "\n",
    "```python\n",
    "import os\n",
    "from langchain.chat_models import init_chat_model\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"sk-...\"\n",
    "\n",
    "llm = init_chat_model(\"openai:gpt-4.1\")\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "9bcbfe01",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.chat_models import ChatTongyi\n",
    "# 或者使用\n",
    "# from langchain_community.llms import Tongyi\n",
    "\n",
    "# 设置通义千问的 API Key\n",
    "# os.environ[\"DASHSCOPE_API_KEY\"] = \"your-dashscope-api-key\"\n",
    "\n",
    "# 初始化通义千问模型\n",
    "llm = ChatTongyi(\n",
    "    model_name=\"qwen-turbo\",  # 或者 \"qwen-plus\", \"qwen-max\"\n",
    "    temperature=0.7,\n",
    "    streaming=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1f42574",
   "metadata": {},
   "source": [
    "将聊天模型集成到一个简单的节点中"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "7254db34",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<langgraph.graph.state.StateGraph at 0x2aa08cb3410>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def chatbot(state: State):\n",
    "    return {\"messages\": [llm.invoke(state[\"messages\"])]}\n",
    "\n",
    "\n",
    "# The first argument is the unique node name\n",
    "# The second argument is the function or object that will be called whenever\n",
    "# the node is used.\n",
    "graph_builder.add_node(\"chatbot\", chatbot)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34a6c015",
   "metadata": {},
   "source": [
    "添加一个 入口 点，以告诉图每次运行时**从何处开始工作**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "417bc090",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<langgraph.graph.state.StateGraph at 0x2aa08cb3410>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "graph_builder.add_edge(START, \"chatbot\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "efbe4e76",
   "metadata": {},
   "source": [
    "在运行图之前，我们需要对其进行编译。我们可以通过在图构建器上调用 compile() 来完成。这将创建一个 CompiledGraph，我们可以在我们的状态上调用它。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "2a606220",
   "metadata": {},
   "outputs": [],
   "source": [
    "graph = graph_builder.compile()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59d9d906",
   "metadata": {},
   "source": [
    "您可以使用 get_graph 方法和其中一个“绘图”方法（例如 draw_ascii 或 draw_png）来可视化图。这些 draw 方法都需要额外的依赖项。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d6dc335a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import Image, display\n",
    "\n",
    "try:\n",
    "    display(Image(graph.get_graph().draw_mermaid_png()))\n",
    "except Exception:\n",
    "    # This requires some extra dependencies and is optional\n",
    "    pass"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f41b5fd",
   "metadata": {},
   "source": [
    "运行聊天机器人,通过键入 quit、exit 或 q 来退出聊天循环。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "6e417a58",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Assistant: 我是通义千问，是阿里巴巴集团旗下的通义实验室自主研发的超大规模语言模型。我的中文名是通义千问，英文名是Qwen。我能够回答问题、创作文字、编程、逻辑推理等多种任务，旨在为用户提供高质量的信息服务和帮助。如果你有任何问题或需要帮助，我会尽力为你提供支持。\n",
      "Assistant: 你好，Wilson！很高兴认识你。有什么我可以帮你的吗？😊\n",
      "Assistant: “我是谁？”这个问题是哲学、心理学和宗教中一个深刻而复杂的问题。从不同的角度来看，可能会有不同的答案：\n",
      "\n",
      "### 1. **从哲学的角度**\n",
      "- **笛卡尔**说：“我思故我在。”（*Cogito, ergo sum*）——你存在的证明是你在思考。\n",
      "- **佛教**认为，“我”是虚幻的，是五蕴（色、受、想、行、识）的暂时组合，没有永恒不变的“自我”。\n",
      "- **存在主义**（如萨特）认为，“我”是通过选择和行动定义的，人是自由的，必须为自己的存在负责。\n",
      "\n",
      "### 2. **从心理学的角度**\n",
      "- **弗洛伊德**将“我”分为本我（潜意识欲望）、自我（现实中的理性部分）和超我（道德规范）。\n",
      "- **现代心理学**认为，“自我”是通过经验、记忆、社会关系和文化构建的，是一个动态的过程，而非固定不变的本质。\n",
      "\n",
      "### 3. **从宗教或灵性的角度**\n",
      "- 在**基督教**中，“我是谁”可能与上帝的爱、救赎和使命有关。\n",
      "- 在**印度教**中，“我”（Atman）被认为是与宇宙本体（Brahman）同一的永恒灵魂。\n",
      "- 在**道家**思想中，“我”可能是自然的一部分，追求与“道”的合一。\n",
      "\n",
      "### 4. **从日常生活的角度**\n",
      "- 你是**一个独特的个体**，拥有自己的思想、情感、经历和价值观。\n",
      "- 你是**你所做的一切**：你的选择、你的行为、你与他人的关系。\n",
      "- 你也是**你所相信的**：你对世界的理解、你对意义的追寻。\n",
      "\n",
      "### 5. **或许更简单一点：**\n",
      "“你是你自己。”  \n",
      "你不需要去寻找一个终极的答案，因为“你是谁”是一个不断被重新定义的过程。你可以在探索中成长，在体验中理解自己。\n",
      "\n",
      "如果你愿意，可以告诉我更多关于你的经历或想法，我可以帮你一起思考这个问题。\n",
      "Goodbye!\n"
     ]
    }
   ],
   "source": [
    "def stream_graph_updates(user_input: str):\n",
    "    for event in graph.stream({\"messages\": [{\"role\": \"user\", \"content\": user_input}]}):\n",
    "        for value in event.values():\n",
    "            print(\"Assistant:\", value[\"messages\"][-1].content)\n",
    "\n",
    "\n",
    "while True:\n",
    "    try:\n",
    "        user_input = input(\"User: \")\n",
    "        if user_input.lower() in [\"quit\", \"exit\", \"q\"]:\n",
    "            print(\"Goodbye!\")\n",
    "            break\n",
    "        stream_graph_updates(user_input)\n",
    "    except:\n",
    "        # fallback if input() is not available\n",
    "        user_input = \"What do you know about LangGraph?\"\n",
    "        print(\"User: \" + user_input)\n",
    "        stream_graph_updates(user_input)\n",
    "        break"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "MLOps",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
